package com.xjoyt.pay.master.dao.predicate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;

import com.xjoyt.pay.annotations.PredicateCommand;
import com.xjoyt.pay.constants.DateConstant;
import com.xjoyt.pay.master.params.OrderPageParam;
import com.xjoyt.pay.master.po.Order;

public class OrderCommands {

	@PredicateCommand
	public List<Predicate> parentIdCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (StringUtils.isBlank(param.parentId))
			return null;
		List<Predicate> list = new ArrayList<>();
		list.add(cb.or(cb.equal(root.get("merchant").get("distributor").get("company").get("id"), param.parentId), cb
				.like(root.get("merchant").get("distributor").get("company").get("path"), "%" + param.parentId + "%")));
		return list;
	}
	
	@PredicateCommand
	public List<Predicate> merchantIdCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (StringUtils.isBlank(param.merchantId))
			return null;
		List<Predicate> list = new ArrayList<>();
		list.add(cb.or(cb.equal(root.get("merchant").get("id"), param.merchantId)));
		return list;
	}

	@PredicateCommand
	public List<Predicate> distributorIdCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (StringUtils.isBlank(param.distributorId))
			return null;
		List<Predicate> list = new ArrayList<>();
		list.add(cb.equal(root.get("merchant").get("distributor").get("id"), param.distributorId));
		return list;
	}

	@PredicateCommand
	public List<Predicate> queryCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (StringUtils.isBlank(param.query))
			return null;
		List<Predicate> list = new ArrayList<>();
		for (String string : param.query.split(" ")) {
			if (StringUtils.isBlank(string))
				continue;
			String like = "%" + string + "%";
			list.add(cb.or(cb.like(root.get("no"), like), cb.like(root.get("merchantNo"), like),
					cb.like(root.get("merchantName"), like)));
		}
		return list;
	}

	@PredicateCommand
	public List<Predicate> queryByChannelCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (StringUtils.isBlank(param.queryByChannel))
			return null;
		List<Predicate> list = new ArrayList<>();
		list.add(cb.or(cb.equal(root.get("orderConfig").get("channelName"), param.queryByChannel),
				cb.equal(root.get("orderConfig").get("channelNo"), param.queryByChannel)));
		return list;
	}

	@PredicateCommand
	public List<Predicate> addedDateCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		List<Predicate> list = new ArrayList<>();
		if (param.startDate == null || param.endDate == null)
			return null;

		String start = DateFormatUtils.format(param.startDate, DateConstant.DATE_FORMAT_PATTERN);
		String end = DateFormatUtils.format(param.endDate, DateConstant.DATE_FORMAT_PATTERN);
		if (StringUtils.isBlank(param.startTime) || StringUtils.isBlank(param.endTime)) {
			end += " 23:59:59";
			start += " 00:00:00";
		} else {
			start += " " + param.startTime;
			end += " " + param.endTime;
		}
		Date startDate = null, endDate = null;
		try {
			startDate = DateUtils.parseDate(start, new String[] { DateConstant.DATE_TIME_FORMAT_PATTERN });
			endDate = DateUtils.parseDate(end, new String[] { DateConstant.DATE_TIME_FORMAT_PATTERN });
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (startDate == null || endDate == null)
			return null;
		list.add(cb.between(root.get("addedDate"), param.startDate, param.endDate));
		return list;
	}

	@PredicateCommand
	public List<Predicate> checkDateCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		List<Predicate> list = new ArrayList<>();
		if (param.checkStartDate == null || param.checkEndDate == null)
			return null;
		list.add(cb.between(root.get("checkDate"), param.checkStartDate, param.checkEndDate));
		return list;
	}

	@PredicateCommand
	public List<Predicate> successCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.success == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		if (param.success)
			list.add(cb.equal(root.get("success"), param.success));
		else
			list.add(cb.or(cb.equal(root.get("success"), false), cb.isNull(root.get("success"))));
		return list;
	}

	@PredicateCommand
	public List<Predicate> doneCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.done == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		if (param.done.success == null)
			list.add(cb.isNull(root.get("done")));
		else
			list.add(cb.equal(root.get("done"), param.done.success));
		return list;
	}

	@PredicateCommand
	public List<Predicate> notifyCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.notify == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		if (param.notify)
			list.add(cb.equal(root.get("notify"), param.notify));
		else
			list.add(cb.or(cb.equal(root.get("notify"), false), cb.isNull(root.get("notify"))));
		return list;
	}

	@PredicateCommand
	public List<Predicate> payCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.pay == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		if (param.pay.success == null)
			list.add(cb.isNull(root.get("pay")));
		else
			list.add(cb.equal(root.get("pay"), param.pay.success));
		return list;
	}

	@PredicateCommand
	public List<Predicate> payTypeCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.payType == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		list.add(cb.equal(root.get("payType"), param.payType));
		return list;
	}

	@PredicateCommand
	public List<Predicate> tradeTypeCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.tradeType == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		list.add(cb.equal(root.get("tradeType"), param.tradeType));
		return list;
	}

	@PredicateCommand
	public List<Predicate> checkCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.check == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		if (param.check)
			list.add(cb.equal(root.get("check"), param.check));
		else
			list.add(cb.or(cb.equal(root.get("check"), false), cb.isNull(root.get("check"))));
		return list;
	}

	@PredicateCommand
	public List<Predicate> backCommand(OrderPageParam param, Root<Order> root, CriteriaQuery<?> query,
			CriteriaBuilder cb) {

		if (param.back == null)
			return null;
		List<Predicate> list = new ArrayList<>();
		if (param.back)
			list.add(cb.equal(root.get("back"), param.back));
		else
			list.add(cb.or(cb.equal(root.get("back"), false), cb.isNull(root.get("back"))));
		return list;
	}

}
